<?php
/**
 * Created by Zhy
 * User: Zhy
 * Date: 2020/6/15
 * Time: 16:30
 */

namespace app\api\controller;


use think\Db;

class Timing
{
    /**
     * 支付宝
     * @var array
     */
    protected $config = array(
        'partner' => '2088621781822784',//用不着
        'seller_id' => 'admin@bagepanzi.com',//用不着
        'sign_type' => 'RSA2',// 直接写死了
        'it_b_pay' => '10m',//用不着
        'md5' => 'djqm7budkdlki6a76yasuyb9s1riiu1j',//用不着
        'ali_public' => 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnM8TA9p3CmsjvYQmHViw6n7QPnlp0SwUkJNgPGRW6O96YugUDtNUuEmG6pDvwNchMRXKTdCig8/UgiWK55Vej7aXf/VS9H1H2LMDB4wAZm768xss+NQdbiQGF/kMkqJT0AUlhjc/+jF5E6oRO62Z/j7zL1qyxCxAb2zq8nnZ6KTqGSAnRKelWMaxBmEKYQCkzS0/aAT6/mfoK1jwS9N1S1OqUADVQqFcOC98go3zIhiayAdAYDGW/Wd3GnHay2xqnFEx0lMV1WB6dhS6rSFnlhBDhofvI1icz85A4e82pL0IZjOQOSRWW9OSJgbkQ7War7RbPAm9MBWbCcnM/uVckwIDAQAB',
        'public_key' => "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4j37rEeEbCxMV+xHLf3lZBPfnVsIjDtVs9mkbsdcDAB11ROCikpxAKIgn2mzlraOhltzVBPI79ghbGCYNlm5Jr9vtoyu2u7pHh/GlkHQZllT0ZMNaBhhx5c8l4Kyb/abtIkh7qQtsT7SefifjZRp4te8NcId+CIsWrie4+WszdToBbSl7tJsG8K6pQv3p7/E8ypWbTHPNXIlCJjfKd29mmutHJBHGjERLaCGj5Jn7h/4rvJrARiQTOgnwP8VDJUbJj2/GstDoGgyBgPMe/eGzcvf36uxOVIEikDIICQFMkwWR1/a1RzyXcK3TOutMuGrEFYOEXwQrR9BVr4RIMyYwIDAQAB",
        'private_key' => 'MIIEowIBAAKCAQEAq4j37rEeEbCxMV+xHLf3lZBPfnVsIjDtVs9mkbsdcDAB11ROCikpxAKIgn2mzlraOhltzVBPI79ghbGCYNlm5Jr9vtoyu2u7pHh/GlkHQZllT0ZMNaBhhx5c8l4Kyb/abtIkh7qQtsT7SefifjZRp4te8NcId+CIsWrie4+WszdToBbSl7tJsG8K6pQv3p7/E8ypWbTHPNXIlCJjfKd29mmutHJBHGjERLaCGj5Jn7h/4rvJrARiQTOgnwP8VDJUbJj2/GstDoGgyBgPMe/eGzcvf36uxOVIEikDIICQFMkwWR1/a1RzyXcK3TOutMuGrEFYOEXwQrR9BVr4RIMyYwIDAQABAoIBAAHv1fzX+yLv/9Ay6GkOmrkRnBQtdz8bllJ4nQvgNQDjSeIIjakHtfUEok325T9HP1eQmfDLi1k3+/sGehZl3geOyHazOAdtu/yrb6P4hWB0PvSaMpoYaYGBEkOaVDza8bh2nvr5XFD0AHJhL+mE638cz8Gga/QOkPyP3GbQxD7ZyFCnm3de9OkpX6PBXZt1IPZr7Zc8N5ze78U2ZRmxojEQb4oFtaxuvZZooJlefJtPzddRc8eD/9Ff+LaoWC5OXzoLKyWRQ+1N07KhRvtu3TXghrZwhJijmw3QbrxEdqwgHPWgLIZtpVw+IUUykln7RwiFlRWSa1mZ4roTZWoEgWECgYEA6rui7OOHvtESmEGpA/g/LXEu0sCIjsfy8EqSXn8Ah87VCUlFlSqPL4NqaL+XhIqiQ2tK2zc/0IV+fOm6RUV5gHxpttBn9QihBdHQsfPy8/tzHloW1uFMmOCvSk6coECPGcf6z19GgFP5Q8iaSxbhc6W/UMRYcAAD6Q8hzxEIrQUCgYEAuxOHOnfcREI0CnxKLmH348erq/2QQGID1XfcthWdSY0SXJyPBoiKAa0odsLAYNPoLCoxlvFijRtC8l2+Ws+RjTiyTF8R7GjnLXwrIX5jF4hVKQc6gxP1gQmF/GIUvGzc/9MqPw90bJQcY65A+6RFDY9KH0UNAlRAYMZwsFKkPkcCgYA+3oyvp+1GpVa2ovdy0b2SHTtuRRUOMO2XgFGdr6Rju3kBqLdTUXfSQP9yGMarQDpfllARUMXtwqNzL2KthQMa77ecuErvrST7mwurbexHfrSBj52IZgWO+LbaTx3SKhhpzk8V1a3bVyJvDj6NGA7AW8dXCY+qR8bEWEI05JoPRQKBgCo3JOvvwlfw7Jd1JrRCzVKsazP7m0K8G4tfagH47K59VChr9+aMh0ALmDb8ibcP+rOErf4W6JtZDIlu2BbcAkdxBOMxDPVhUtGz1HPRdoEH9de1VuHfbiY5RPAIHg/LLS/Zsg3a6fXaknF4EBf5INAHhr15so7U/lYYUbOoYoHfAoGBAMkg7svBwNGz+OMiRGCcwUtuI66nw+MwhYkSXQrWHd0CarMkqkQV9hdiTHgwTiR86eJcCAgItEa+Py+2oSJE3K7SBCUlAZnmELGzXnDf15PJ+mT6S7LtCNoks9/2YbP3j2MjKmhXgaOG6YHxjxZ+UARlV4mVk+qZbPNsYQxJ1gAR'
    );
    
    /**
     * 微信
     * @var array
     */
    private $config1 = array(
        'APPID' => 'wx9feafce4eccb4728', // 微信支付APPID.
        'MCHID' => '1582362791', // 微信支付MCHID 商户收款账号
        'KEY' => 'NwyWVrJJX35zMM8nB2PaYPaoMVNssdH3', // 微信支付KEY
//        'APPSECRET' => '6a54b5e88c2dd87159bfeca466a9a770', // 公众帐号secert (公众号支付专用)
//        'NOTIFY_URL' => 'http://heart.xuanwumobile.com/api/Weixin/huidiao', // 接收支付状态的连接
    );
    
    /**
     * 修改训练状态
     * 次日失效
     * 48小时删除
     */
    public function changeDrillStatus(){
        $today = date('Y-m-d 00:00:00');
        $del_time = date('Y-m-d H:i:s', strtotime('-48 hours'));
        // 失效
        Db::table('up_sailboat_drill')
            ->where('drill_create_time', '<', $today)
            ->where('drill_status', 'IN', '1,2,3')
            ->setField('drill_status', 4);
        
        // 删除
        Db::table('up_sailboat_drill')
            ->where('drill_create_time', '<=', $del_time)
            ->where('drill_status', 4)
            ->setField('drill_status', 5);
    }
    
    /**
     * 修改比赛状态
     * 未开始---进行中
     * 进行中---已结束
     */
    public function matchStatus(){
        $time = date('Y-m-d H:i:s');
        // 未开始->进行中
        Db::table('up_match')
            ->where('match_status', 1)
            ->where('match_start_time', '<=', $time)
            ->setField('match_status', 2);
        
        // 进行中->结束（可能永远都不会跑这个定时任务）
        Db::table('up_match')
            ->where('match_status', 2)
            ->where('match_end_time', '<=', $time)
            ->where('match_real_end_status', 2)
            ->setField('match_status', 3);
    }
    
    /**
     * 已取消比赛退款----一个一个退
     * 一分钟跑一次
     */
    public function loseMatch(){
        $info = Db::table('up_match_apply_info')
            ->join('up_match', 'match_id = ma_match_id', 'left')
            ->where('ma_apply_status', 2)
            ->where('match_status', 4)
//            ->where('ma_role', 1)
            ->field('ma_user_id, ma_match_id, match_title, match_cancel_reason, 
            ma_id, ma_real_pay_user_id')
            ->find();
        if($info){
            // 订单信息
            $order = Db::table('up_order')
                ->where('order_user_id', $info['ma_real_pay_user_id'])
                ->where('order_match_id', $info['ma_match_id'])
                ->field('order_id, order_num, order_price, order_phone, order_type')
                ->find();
            
            $order_return_num = date('YmdHis') . rand(000000, 999999);
            Db::table('up_order')->where('order_id', $order['order_id'])->setField('order_return_num', $order_return_num);
            
            // 退款
            if($order['order_type'] == 1 || $order['order_type'] == 3){ // 微信
                $res = $this->weixiReturn($order['order_price'], $order['order_price'], $order['order_num'], $order_return_num);
            }else{
                $res = $this->aliReturn($order['order_price'], $order['order_num']);
            }
            if($res['status'] == 200){
                $user_arr = Db::table('up_match_apply_info')
                    ->where('ma_order_num', $order['order_num'])
                    ->column('ma_user_id');
                if(in_array($info['ma_real_pay_user_id'], $user_arr)){
                    $user_ids = implode(',', $user_arr);
                }else{
                    $user_ids = implode(',', $user_arr) . ',' . $info['ma_real_pay_user_id'];
                }
                
                Db::startTrans();
                try{
                    // 系统信息
                    $notice = [
                        'notice_title' => '赛事取消通知',
                        'notice_content' => '您好，因“' . $info['match_cancel_reason'] . '”原因，“' . $info['match_title'] . '”赛事已取消，如有疑问请联系赛事组委会',
                        'notice_range' => 2,
                        'notice_user' => ',0,' . $user_ids . ',',
                        'notice_read_user' => ',0,',
                        'notice_del_user' => ',0,',
                        'notice_type' => 2,
                        'notice_committee_id' => 0,
                        'notice_time' => date('Y-m-d H:i:s')
                    ];
                    Db::table('up_notice')->insert($notice);
                    // 订单状态
                    Db::table('up_order')->where('order_id', $order['order_id'])->setField('order_status', 3);
                    // 报名状态
                    Db::table('up_match_apply_info')
                        ->where('ma_order_num', $order['order_num'])
                        ->setField('ma_apply_status', 3);
                    Db::commit();
                }catch(\Exception $e){
                    Db::rollback();
                }
                // 推送
                $list = [];
                $send_arr = explode(',', $user_ids);
                foreach($send_arr as $k => $v){
                    array_push($list, (string)$v);
                }
                try{
                    $this->Jpush(1, $list, '赛事取消通知', ['send_type' => 1, 'match_id' => $info['ma_match_id']]);
                }catch(\Exception $e){
                    
                }
                // 用户信息
                $user_phone = Db::table('up_u_user')
                    ->where('user_id', 'IN', $user_ids)
                    ->column('user_phone');
                $phone_arr = implode(',', $user_phone);
                // 短信
                $reason = $info['match_cancel_reason'];
                $title = $info['match_title'];
                YzxSms("$reason,$title", $phone_arr, '', 2);
            }
        }
    }
    
    //**************************************** 支付宝
    /**
     * 阿里退款
     * @param $money   退款金额
     * @param $num     订单号
     */
    public function aliReturn($money, $num)
    {
        $payInfo = array();
        $payInfo['number'] = $num;
        $payInfo['money'] = $money;
        //仨参数：money,number
        import('alipay.aop.AopClient', EXTEND_PATH);
        import('alipay.aop.request.AlipayTradeRefundRequest', EXTEND_PATH);
        $aop = new \AopClient;
        $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $aop->appId = '2021001162653764';
        $aop->rsaPrivateKey = $this->config['private_key'];
        $aop->alipayrsaPublicKey = $this->config['ali_public']; //不应该用这个，用ali_public
        $aop->apiVersion = '1.0';
        $aop->signType = 'RSA2';
        $aop->postCharset = 'UTF-8';
        $aop->format = 'json';
        $request = new \AlipayTradeRefundRequest;
        $refundAmount = $payInfo['money'];
        $request->setBizContent("{" .
            "\"out_trade_no\":\"" . $payInfo['number'] . "\"," .
            "\"trade_no\":\"\"," .
            "\"refund_amount\":" . $refundAmount . "," .
            "\"refund_reason\":\"退款\"" .
            "  }");
        $result = $aop->execute($request);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if(!empty($resultCode) && $resultCode == 10000) {
            return array('status' => 200, 'msg' => '操作成功');
        } else {
            return array('status' => 0, 'msg' => '调用接口失败');
        }
    }
    
    //************************************* 微信
    /**
     * 微信退款
     * @param $total_fee       订单金额
     * @param $refund_fee      退款金额
     * @param $out_trade_no    付款时的订单号
     * @param $out_refund_no   退款订单号
     * @return array
     */
    public function weixiReturn($total_fee, $refund_fee, $out_trade_no, $out_refund_no){
        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund'; //请求地址
        //请求数据
        $config_data = [
            'appid' => $this->config1['APPID'],
            'mch_id' => $this->config1['MCHID'],
            'nonce_str' => $this->getRandChar(32),
            'out_trade_no' => $out_trade_no, //支付订单号
            'out_refund_no' => $out_refund_no, //退款单号
            'total_fee' => $total_fee * 100, //订单金额
            'refund_fee' => $refund_fee * 100, //退款金额
        ];
        $config_data['sign'] = $this->makeSign($config_data);
        $data = $this->toXml($config_data);
        $responseArr = $this->toArray($this->httpRequest($url, $data));
//        return $res;
        if(!is_array($responseArr) || count($responseArr)<=0){
            $return['msg'] = '网络请求繁忙';
            $return['status'] = 0;
        }else if($responseArr['return_code'] == 'FAIL'){
            $return['msg'] = $responseArr['return_msg'];
            $return['status'] = 0;
        }else{
            //二次签名
            $return['text'] = $responseArr;
//			直接返回
            $return['status'] = 200;
        }
        return $return;
        
    }
    
    /*
     * 发送请求
     * @param  string $url      请求的url地址
     * @param  array  $postData 请求的数据
     */
    public function httpRequest($url, $postData = [])
    {
        $header[] = "Content-type: text/xml";//定义content-type为xml,注意是数组
        // 初始化curl
        $ch = curl_init();
        // 设置请求的url地址
        curl_setopt($ch, CURLOPT_URL, $url);
        // 将curl_exec()获取的信息以字符串返回，而不是直接输出。
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        // 发送post请求
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        //curl注意事项，如果发送的请求是https，必须要禁止服务器端校检SSL证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'pem');
        curl_setopt($ch,CURLOPT_SSLCERT,ROOT_PATH.'/public/apiclient_cert.pem');
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'pem');
        curl_setopt($ch,CURLOPT_SSLKEY,ROOT_PATH.'/public/apiclient_key.pem');
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        
        // 执行curl
        $result = curl_exec($ch);
        if(curl_errno($ch)){
            print curl_error($ch);
        }
        // 关闭curl
        curl_close($ch);
        
        return $result;
    }
    
    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    public function makeSign($data){
        // 去空
        $data=array_filter($data);
        //签名步骤一：按字典序排序参数
        ksort($data);
        $string_a=http_build_query($data);
        $string_a=urldecode($string_a);
        //签名步骤二：在string后加入KEY
        $config1=$this->config1;
        $string_sign_temp=$string_a."&key=".$config1['KEY'];
        //签名步骤三：MD5加密
        $sign = md5($string_sign_temp);
        // 签名步骤四：所有字符转为大写
        $result=strtoupper($sign);
        return $result;
    }
    
    /**
     * 输出xml字符
     * @throws WxPayException
     **/
    public function toXml($data){
        //var_dump($data);
        if(!is_array($data) || count($data) <= 0){
            //throw new WxPayException("数组数据异常！");
        }
        $xml = "<xml>";
        foreach ($data as $key=>$val){
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }
    
    /**
     * 将xml转为array
     * @param  string $xml xml字符串
     * @return array       转换得到的数组
     */
    public function toArray($xml){
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $result;
    }
    
    /**
     * 获取指定长度的随机字符串
     * @param $length
     * @return null|string
     */
    function getRandChar($length){
        $str = null;
        $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
        $max = strlen($strPol)-1;
        for($i=0;$i<$length;$i++){
            $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数
        }
        return $str;
    }
    
    /**
     * 极光推送
     * @param $type 1:推送个人  2:推送全体
     * @param $alias 别名 user_id OR token
     * @param $message 推送消息内容
     * @param $extras 扩展字段接受数组
     * @return array
     */
    public function Jpush($type,$alias,$message,$extras)
    {
//        $alias = (string)$alias;
        import('jpush.autoload', EXTEND_PATH);
        //初始化JPushClient
        $client = new \JPush\Client(config('jpush.appKey'),config('jpush.masterSecret'));
        //生成推送Payload构建器
        $push = $client->push();
        //推送平台 'all'  OR  ['ios','android']  OR  'ios','android'
        $push->setPlatform('all');
        //1:推送个人  2:推送全体
        if($type==1){
            $push->addAlias($alias);//按别名推送
        }else{
            $push->addAllAudience();//广播消息推送
        }
        //IOS推送
        $push->iosNotification($message, [
                'alert'=>$message,
                'badge' => '+1',
                'extras' => $extras,
                'sound'=>'default'
            ]
        );
        //Android推送
        $push->androidNotification($message, [
                'alert'=>$message,
                'extras' => $extras
            ]
        );
        return $push->send();
    }
}